#include "rsa.h"

Rsa::Rsa() {
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();
}
Rsa::~Rsa() {
    EVP_cleanup();
    ERR_free_strings();
}

// 生成RSA密钥对
bool Rsa::generateRSAKey(RSA*& rsa, int keySize) {
    rsa = RSA_new();
    BIGNUM* bn = BN_new();

    if (!bn) {
        throw std::runtime_error("generateRSAKey 无法创建BIGNUM对象>>1");
    }

    // 生成随机数种子
    if (RAND_poll() != 1) {
        BN_free(bn);
        RSA_free(rsa);
        throw std::runtime_error("generateRSAKey 随机数生成失败>>2");
    }

    // 设置公钥指数为65537 (常见选择)
    if (BN_set_word(bn, RSA_F4) != 1) {
        BN_free(bn);
        RSA_free(rsa);
        throw std::runtime_error("generateRSAKey 无法设置公钥指数>>3");
    }

    // 生成密钥对
    if (RSA_generate_key_ex(rsa, keySize, bn, nullptr) != 1) {
        BN_free(bn);
        RSA_free(rsa);
        throw std::runtime_error("generateRSAKey RSA密钥生成失败>>4");
    }

    BN_free(bn);
    return true;
}

// 保存RSA密钥到文件
bool Rsa::saveRSAKey(const RSA* rsa, const std::string& filename, bool isPrivate) {
    FILE* file = fopen(filename.c_str(), "w");
    if (!file) {
        throw std::runtime_error("saveRSAKey 无法打开文件: " + filename);
    }

    int result;
    if (isPrivate) {
        result = PEM_write_RSAPrivateKey(file, const_cast<RSA*>(rsa), nullptr, nullptr, 0, nullptr, nullptr);
    } else {
        result = PEM_write_RSAPublicKey(file, const_cast<RSA*>(rsa));
    }

    fclose(file);

    if (result != 1) {
        throw std::runtime_error("saveRSAKey 无法写入密钥到文件: " + filename);
    }

    return true;
}

// 从文件加载RSA密钥
RSA*  Rsa::loadRSAKey(const std::string& filename, bool isPrivate) {
    FILE* file = fopen(filename.c_str(), "r");
    if (!file) {
        throw std::runtime_error("loadRSAKey 无法打开文件: " + filename);
    }

    RSA* rsa = nullptr;
    if (isPrivate) {
        rsa = PEM_read_RSAPrivateKey(file, nullptr, nullptr, nullptr);
    } else {
        rsa = PEM_read_RSAPublicKey(file, nullptr, nullptr, nullptr);
    }

    fclose(file);

    if (!rsa) {
        throw std::runtime_error("loadRSAKey 无法从文件加载密钥: " + filename);
    }

    return rsa;
}

// 使用公钥加密数据
std::vector<unsigned char>  Rsa::rsaEncrypt(const RSA* rsa, const std::vector<unsigned char>& data) {
    int keySize = RSA_size(rsa);
    std::vector<unsigned char> encrypted(keySize);

    // 计算最大可加密的数据大小
    int maxDataSize = keySize - 42; // 对于PKCS#1 OAEP填充
    if (data.size() > static_cast<size_t>(maxDataSize)) {
        throw std::runtime_error("rsaEncrypt 数据太大，无法用当前RSA密钥加密");
    }

    int result = RSA_public_encrypt(
        data.size(),
        data.data(),
        encrypted.data(),
        const_cast<RSA*>(rsa),
        RSA_PKCS1_OAEP_PADDING
        );

    if (result == -1) {
        throw std::runtime_error("rsaEncrypt RSA加密失败");
    }

    encrypted.resize(result);
    return encrypted;
}

// 使用私钥解密数据
std::vector<unsigned char>  Rsa::rsaDecrypt(const RSA* rsa, const std::vector<unsigned char>& encryptedData) {
    int keySize = RSA_size(rsa);
    std::vector<unsigned char> decrypted(keySize);

    int result = RSA_private_decrypt(
        encryptedData.size(),
        encryptedData.data(),
        decrypted.data(),
        const_cast<RSA*>(rsa),
        RSA_PKCS1_OAEP_PADDING
        );

    if (result == -1) {
        throw std::runtime_error("rsaDecrypt RSA解密失败");
    }

    decrypted.resize(result);
    return decrypted;
}

// 打印错误信息
void  Rsa::printOpenSSLError() {
    unsigned long errCode;
    while ((errCode = ERR_get_error()) != 0) {
        char errMsg[1024];
        ERR_error_string_n(errCode, errMsg, sizeof(errMsg));
        std::cerr << "OpenSSL错误: " << errMsg << std::endl;
    }
}
